package cn.xzqwjw.taskmanager.config;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import cn.xzqwjw.taskmanager.common.converter.CustomLocalDateDeserializer;
import cn.xzqwjw.taskmanager.common.converter.CustomLocalDateTimeDeserializer;
import cn.xzqwjw.taskmanager.common.converter.CustomLocalTimeDeserializer;
import cn.xzqwjw.taskmanager.utils.JsonUtil;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
import java.util.TimeZone;

/**
 * 自定义json的LocalDateTime的序列化和反序列化
 *
 * @author rush
 */
@Configuration
public class JacksonConfig {

    @Bean
  public Jackson2ObjectMapperBuilderCustomizer customizer() {
    return builder -> {
      builder.locale(Locale.CHINA);
      SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
      TimeZone timeZone = TimeZone.getTimeZone("Asia/Shanghai");
      sdf.setTimeZone(timeZone);
      // builder.timeZone(TimeZone.getTimeZone(ZoneId.systemDefault()));
      builder.dateFormat(sdf);
      builder.timeZone(timeZone);

      JavaTimeModule javaTimeModule = new JavaTimeModule();
      // 添加序列化
      javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
      javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
      javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
      // 添加反序列化
      javaTimeModule.addDeserializer(LocalDateTime.class, new CustomLocalDateTimeDeserializer());
      javaTimeModule.addDeserializer(LocalDate.class, new CustomLocalDateDeserializer());
      javaTimeModule.addDeserializer(LocalTime.class, new CustomLocalTimeDeserializer());

      builder.modules(javaTimeModule);
    };
  }

  /**
   * 将工具类中的 objectMapper 换为 Spring 中的 objectMapper
   */
  @Bean
  @Primary
  @ConditionalOnMissingBean(ObjectMapper.class)
  public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
    ObjectMapper objectMapper = builder.createXmlMapper(false).build();
    // 通过该方法对mapper对象进行设置，所有序列化的对象都将按改规则进行系列化
    // Include.Include.ALWAYS 默认
    // Include.NON_DEFAULT 属性为默认值不序列化
    // Include.NON_EMPTY 属性为 空（""） 或者为 NULL 都不序列化，则返回的json是没有这个字段的
    // Include.NON_NULL 属性为NULL 不序列化
    objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    // 允许出现未用引号的属性名
    objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
    // 允许出现单引号
    objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
    objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    // 忽略无法转换的或者是空的 Bean
    objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
    // 将Long,BigInteger序列化的时候,转化为String
    SimpleModule simpleModule = new SimpleModule();
    simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
    simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
    simpleModule.addSerializer(BigInteger.class, ToStringSerializer.instance);
    objectMapper.registerModule(simpleModule);
    // 将工具类中的 objectMapper 换为 Spring 中的 objectMapper
    JsonUtil.objectMapper = objectMapper;
    return objectMapper;
  }

}
